package com.lovezy.platform.message.mobile.service.impl;

import com.lovezy.platform.core.base.enums.StatusEnum;
import com.lovezy.platform.core.base.enums.TrueOrFalseEnum;
import com.lovezy.platform.core.base.query.Pager;
import com.lovezy.platform.core.base.service.MapperService;
import com.lovezy.platform.core.exception.DefaultErrorCode;
import com.lovezy.platform.core.exception.ServiceException;
import com.lovezy.platform.core.sms.SmsResponse;
import com.lovezy.platform.core.sms.SmsSender;
import com.lovezy.platform.message.mobile.enums.SmsIllegalEnum;
import com.lovezy.platform.message.mobile.enums.SmsTypeEnum;
import com.lovezy.platform.message.mobile.mapper.MobileMapper;
import com.lovezy.platform.message.mobile.model.Mobile;
import com.lovezy.platform.message.mobile.model.MobileExample;
import com.lovezy.platform.message.mobile.service.SmsSenderService;
import com.lovezy.platform.message.mobile.service.SmsServiceTarget;
import com.lovezy.platform.message.mobile.service.VerifyMobileResult;
import lombok.AllArgsConstructor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;

import java.util.Calendar;
import java.util.Date;
import java.util.Optional;
import java.util.function.Function;

/**
 * 短信服务实现
 * Created by jin on 2017/11/10.
 */
@AllArgsConstructor
public class SmsSenderServiceImpl extends MapperService<Mobile,Integer,MobileMapper> implements SmsSenderService{

    private final Log log = LogFactory.getLog(SmsSenderService.class);

    private SmsSender smsSender;

    @Override
    public Mobile sendSms(SmsServiceTarget target) {
        checkTarget(target);
        SmsResponse res = smsSender.send(target);
        if (!res.isSuccess()) {
            log.error(res.getFailReason());
        }
        Date now = new Date();
        Mobile mobile = new Mobile();
        mobile.setMemberId(target.getMemberId());
        mobile.setAuthKey(target.getAuthKey());
        mobile.setFailReason(res.getFailReason());
        mobile.setMobileNumber(target.getMobile());
        mobile.setUsed(TrueOrFalseEnum.FALSE.value());
        mobile.setType(target.getType().value());
        mobile.setGmtCreate(now);
        mobile.setGmtModify(now);
        mobile.setStatus(StatusEnum.NORMAL.value());
        mapper.insert(mobile);
        return mobile;
    }

    @Override
    public void verifyMobile(@NotNull String authKey, @NotNull SmsTypeEnum type, Function<VerifyMobileResult,Boolean> handler) {
        Optional<Mobile> mobileOptional = findMobile(authKey);
        VerifyMobileResult result = new VerifyMobileResult();
        if (!mobileOptional.isPresent()) {
            result.setIllegal(SmsIllegalEnum.NOT_FOUND);
            handler.apply(result);
            return;
        }
        Mobile mobile = mobileOptional.get();
        result.setMobile(mobile);
        if (mobile.getUsed() == TrueOrFalseEnum.TRUE.value()) {
            result.setIllegal(SmsIllegalEnum.ALREADY_USED);
            handler.apply(result);
            return;
        }
        if (mobile.getType() != type.value()) {
            result.setIllegal(SmsIllegalEnum.TYPE_ERROR);
            handler.apply(result);
            return ;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(mobile.getGmtCreate());
        calendar.add(Calendar.MINUTE, 30);
        if (calendar.before(new Date())) {
            result.setIllegal(SmsIllegalEnum.EXPIRE);
            handler.apply(result);
            return;
        }

        result.setSuccess(true);
        Boolean canUpdate = handler.apply(result);
        if (canUpdate) {
            Mobile updateMobile = new Mobile();
            updateMobile.setMobileId(mobile.getMobileId());
            updateMobile.setGmtModify(new Date());
            updateMobile.setUsed(TrueOrFalseEnum.TRUE.value());
            mapper.updateByPrimaryKeySelective(updateMobile);
        }
    }

    private Optional<Mobile> findMobile(@NotNull String authKey) {
        MobileExample example = new MobileExample();
        example.createCriteria()
                .andAuthKeyEqualTo(authKey)
                .andUsedEqualTo(TrueOrFalseEnum.FALSE.value());
        example.setOrderByClause("gmtCreate desc");
        return Pager.doSingleton(() -> mapper.selectByExample(example));
    }

    private void checkTarget(SmsServiceTarget target) {
        if (target.getType() == null) {
            throw new ServiceException(DefaultErrorCode.SERVICE_ERROR, "短信类别为空");
        }
    }


}
